Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 <<   zurück
Visual Basic 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual Basic 2005

Visual Basic 2005
1.233 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-585-1
gp Kapitel 4 Das Klassendesign (Teil 1)
  gp 4.1 Einführung in die Objektorientierung
    gp 4.1.1 Das objektorientierte Paradigma
    gp 4.1.2 Vorteile der objektorientierten Programmierung
    gp 4.1.3 Zusammenfassung
  gp 4.2 Die Klassendefinition
    gp 4.2.1 Die Deklaration von Objektvariablen
    gp 4.2.2 Zugriffsmodifizierer einer Klasse
    gp 4.2.3 Der Projekttyp »Klassenbibliothek«
    gp 4.2.4 Splitten einer Klassendefinition mit »Partial«
    gp 4.2.5 Zusammenfassung
  gp 4.3 Objektmethoden
    gp 4.3.1 Methoden mit Rückgabewert
    gp 4.3.2 Methoden ohne Rückgabewert
    gp 4.3.3 Der Aufruf einer Methode
    gp 4.3.4 Methoden mit Parameterliste
    gp 4.3.5 Rückgabewert einer Methode
    gp 4.3.6 Variablen in einer Methode
    gp 4.3.7 Zugriffsmodifizierer einer Methode
    gp 4.3.8 Referenz- und Wertparameter
    gp 4.3.9 Parameter, die Objektreferenzen erwarten
    gp 4.3.10 Methodenüberladung
    gp 4.3.11 Optionale Parameter
    gp 4.3.12 Zusammenfassung
  gp 4.4 Objekteigenschaften
    gp 4.4.1 Ergänzung der Klasse »Circle«
    gp 4.4.2 Lese- und schreibgeschützte Eigenschaften
    gp 4.4.3 Die Parameterliste einer Property-Prozedur
    gp 4.4.4 Standardeigenschaften
    gp 4.4.5 Das With ... End With-Statement
    gp 4.4.6 Konstanten mit »Const« und »ReadOnly«
    gp 4.4.7 Der Zugriff auf private Daten
    gp 4.4.8 Zusammenfassung
  gp 4.5 Konstruktoren
    gp 4.5.1 Die Konstruktoren in der Klasse »Circle«
    gp 4.5.2 Die Konstruktoraufrufe
    gp 4.5.3 Definition von Konstruktoren
    gp 4.5.4 »Friend«-Konstruktoren
    gp 4.5.5 »Private«-Konstruktoren
    gp 4.5.6 Konstruktorverkettung
    gp 4.5.7 Zusammenfassung
  gp 4.6 Der Destruktor
    gp 4.6.1 Das Zerstören von Objekten
    gp 4.6.2 Der Garbage Collector
    gp 4.6.3 Zusammenfassung
  gp 4.7 Arbeiten mit Objektreferenzen
    gp 4.7.1 Prüfen auf Initialisierung
    gp 4.7.2 Mehrere Referenzen auf ein Objekt
    gp 4.7.3 Typfeststellung einer Objektreferenz
    gp 4.7.4 Zusammenfassung


Galileo Computing

4.6 Der Destruktor  downtop


Galileo Computing

4.6.1 Das Zerstören von Objekten  downtop

Ein Konstruktor wird aufgerufen, wenn das Objekt einer Klasse erzeugt wird. Damit beginnt der Lebenszyklus des Objekts, der dann endet, wenn das Pendant des Konstruktors aufgerufen wird: der Destruktor. Im Destruktor sind oft Anweisungen enthalten, um die von einem Objekt zusätzlich beanspruchten Fremdressourcen freizugeben, die beispielsweise andere Systeme belasten. Dazu gehören unter anderem Netzwerk- oder Datenbankverbindungen, die in einer objektinternen Referenz vorgehalten werden.

Der Umstand, der zur Aufgabe eines konkreten Objekts und dem damit verbundenen Destruktoraufruf führt, kann

gp  das Verlassen des Gültigkeitsbereichs der Objektvariablen oder
gp  die Zuweisung von Nothing an die Objektreferenz

sein. Das bedeutet jedoch nicht, dass beim Eintreten einer dieser beiden Bedingungen augenblicklich der Destruktor ausgeführt wird. Tatsächlich kann das noch eine unbestimmbare Zeit dauern. Mit anderen Worten bedeutet dies, dass das Objekt zwar aus Sicht des Programms nicht mehr existiert, sich jedoch immer noch im Speicher befindet und diesen letztendlich belastet.


Galileo Computing

4.6.2 Der Garbage Collector  downtop

Den Anstoß zum Aufruf des Destruktors gibt ein Mechanismus, der als Garbage Collector (GC) bezeichnet wird. Der Garbage Collector hat die Aufgabe, nach den Objekten zu suchen, die nicht mehr referenziert werden. Diese werden dann endgültig verworfen, d. h., der von den Objekten reservierte Speicherplatz wird freigegeben und kann anschließend von anderen Objekten beansprucht werden. Während des Prozesses komprimiert der Garbage Collector den Heap, so dass eine Fragmentierung die Vergabe von Speicher nicht verhindert, weil kein ausreichend großer Speicherblock zur Verfügung steht.

Wie bereits erwähnt, kann nicht vorhergesagt werden, wann der GC seine Arbeit aufnimmt. Damit stellt sich sofort die Frage, nach welchen Kriterien der GC aktiv wird. Als selbstständige Ausführungseinheit (Thread) genießt der GC keine hohe Priorität und kann erst dann den Prozessor in Anspruch nehmen, wenn die Anwendung beschäftigungslos ist. Theoretisch könnte das bedeuten, dass eine viel beschäftigte Anwendung dem GC keine Chance lässt, jemals aktiv zu werden. Es gibt aber eine wichtige Einschränkung: Noch bevor den Speicherressourcen der Anwendung die »Luft ausgeht«, ist die zweite Bedingung erfüllt, um die Speicherbereinigung mit dem GC anzustoßen.


Der Garbage Collector wird spätestens dann nach allen aufgegebenen Objekten suchen und deren Speicherplatz freigeben, wenn die Speicherressourcen knapp werden.


Der Anstoß dazu kann auch im Programmcode unter Aufruf der statischen Methode Collect der Klasse GC gegeben werden:


GC.Collect()

Die Suche nach allen freigegebenen Objekten nimmt natürlich Zeit in Anspruch und führt zu Performanceverlusten der laufenden Anwendung. Daher ist es nicht empfehlenswert, ohne ein gewichtiges Argument bei jeder Objektzerstörung »zur Sicherheit« zusätzlich den Bereinigungsprozess zu aktivieren.

Die Finalize-Methode

Der Garbage Collector ist als Speicherbereinigungsprozess für die Freigabe der lokalen Ressourcen verantwortlich. Er ist allerdings nicht in der Lage, die Aufräumarbeiten anzustoßen, die von fremden Rechnern für das zu zerstörende Objekt bereitgestellt werden. Was ist darunter zu verstehen?

Wird ein Objekt beispielsweise dazu benutzt, eine Datenbankverbindung zu einer Datenbank wie dem Microsoft SQL Server zu öffnen, enthält nicht nur das Objekt Verbindungsinformationen, sondern auch der SQL Server reserviert seinerseits Ressourcen für die geöffnete Verbindung. Versäumen Sie, dem SQL Server mitzuteilen, dass das Objekt zerstört und die Verbindung nicht weiter beansprucht wird, werden die vom Objekt belegten Ressourcen für die Verbindung zwar nach dessen Zerstörung freigegeben, nicht aber die, die der SQL Server dafür bereitstellt. Im Extremfall, wenn sehr viele Clients die Dienste der Datenbank in Anspruch nehmen und die Verbindung nicht ordentlich schließen, kann das serverseitig zu Problemen führen, da die Gesamtanzahl der Zugriffe nicht unbegrenzt ist.

Da der GC nur den lokalen Speicher bereinigt, muss es eine andere Möglichkeit geben, um auch die entfernten Ressourcen bei der Zerstörung freizugeben oder zumindest den Anstoß dazu zu geben. Letztendlich muss der Entwickler selbst für diese Aktion sorgen und den entsprechenden Code dafür schreiben. Es gibt eine Methode, die der Garbage Collector kennt und – soweit implementiert – ausführt. Diese heißt Finalize.

Hat der Aufräummechanismus ein Objekt entdeckt, das nicht mehr referenziert wird, sucht er in diesem Objekt nach der Methode Finalize. Nicht jedes Objekt muss zwangsläufig diese Methode bereitstellen, aber wenn sie vorhanden ist, wird sie kurz vor der endgültigen Zerstörung des Objekts noch ausgeführt.

Die Definition mit


Protected Overrides Sub Finalize()
...
MyBase.Finalize()
End Sun

sieht im ersten Moment für Sie wegen des Modifizierers Overrides ungewöhnlich aus, hängt aber mit dem Vererbungskonzept zusammen und darf daher nicht anders lauten. In Kapitel 6 werden wir uns mit der Vererbung beschäftigen, nehmen Sie daher Overrides einfach als notwendig hin. Innerhalb der Methode stehen alle notwendigen Anweisungen zur Verfügung, um den entfernten Rechner mit den Informationen zu versorgen, dass er in Eigeninitiative die erforderlichen Maßnahmen ergreift. Die Anweisung


MyBase.Finalize()

ist immer die letzte Anweisung innerhalb von Finalize und ruft die gleichnamige, geerbte Methode der direkten Basisklasse auf. Die Referenz MyBase verweist auf die Basisklasse, ähnlich wie Me der Verweis eines Objekts auf sich selbst darstellt.

Vor der Zerstörung eines freigegebenen Objekts prüft der Garbage Collector zunächst, ob die Klasse des Objekts Finalize bereitstellt. Wenn ja, wird sie ausgeführt und im Anschluss daran der vom Objekt reservierte Speicher wieder freigegeben. Die natürliche Folge dieses Arbeitsaufwands ist ein gewisser Performanceverlust der Anwendung. Daher sollten Sie sich immer an die folgende Regel halten:


Implementieren Sie die Finalize-Methode nur dann, wenn sie auch tatsächlich benötigt wird.


Der Garbage Collector in Aktion

Nun wollen wir natürlich einmal den Garbage Collector bei seiner Arbeit beobachten. Dazu wird im folgenden Beispiel die Klasse GCTestClass definiert, welche die Finalize-Methode implementiert und bei deren Aufruf eine Meldung an der Konsole ausgegeben wird, die eine interne Kennnummer enthält.


' ----------------------------------------------------------
' Beispiel: ...\Kapitel 4\GarbageCollector
' ----------------------------------------------------------
Module Module1
Dim obj1 As GCTestClass
Sub Main()
obj1 = New GCTestClass(1)
Dim obj3 As New GCTestClass(3)
obj3 = Nothing
MyProc()
Console.ReadLine()
System.GC.Collect()
Console.ReadLine()
End Sub
Public Sub MyProc()
Dim obj2 As New GCTestClass(2)
End Sub
End Module
' --------------------- Testklasse --------------------
Public Class GCTestClass
Private number As Int32
Public Sub New(ByVal x As Int32)
number = x
End Sub
Protected Overrides Sub Finalize()
Console.WriteLine("Destruktor / Objekt-Nr.{0}", number)
MyBase.Finalize()
End Sub
End Class

Innerhalb des Moduls sind drei verschiedene Objektvariablen deklariert: eine globale (obj1) sowie zwei lokale (obj2 und obj3). Damit lässt sich für jedes Objekt eine unterschiedliche Lebensdauer festlegen: obj1 wird zerstört, wenn die Anwendung beendet wird, obj2 nach dem Verlassen der Methode MyProc. Die Zerstörung von obj3 wird mit Setzen auf Nothing angestoßen.

Um den Garbage Collector auf jeden Fall zur Aktivität anzuspornen, wird in Main die Methode Collect der Klasse GC aufgerufen.

Wenn Sie die Anwendung starten, werden Sie nach dem ersten Drücken der (Enter)-Taste die Collect-Methode aufrufen und die Meldung der beiden Finalisierer der Objekte obj2 und obj3 sehen. Die Meldung des letzten Objekts können Sie nach einer weiteren Betätigung der (Enter)-Taste noch kurz erkennen, bevor das Konsolenfenster geschlossen wird.

Die »Dispose«-Methode

Ein unter Umständen nicht akzeptabler Nachteil ist mit der Finalize-Methode verbunden: Wenn sie implementiert ist kann nicht exakt vorherbestimmt werden, wann sie zur Ausführung kommt.

Wie Sie bereits wissen, werden die Aufräumarbeiten dann angestoßen, wenn durch die Beschäftigungslosigkeit einer laufenden Anwendung der niedrigprioritäre Thread des Garbage Collectors seine Arbeit aufnimmt oder sich die Speicherressourcen verknappen. Tatsächlich sind sogar Situationen denkbar, die niemals zu einer Ausführung von Finalize führen – denken Sie nur an den Absturz des Rechners. Folgerichtig kann auch nicht garantiert werden, dass der GC überhaupt jemals einmal seine Aufgabe verrichtet.

Wenn ein Objekt aber kostspielige oder begrenzte Ressourcen beansprucht, muss sichergestellt werden, dass diese so schnell wie möglich wieder freigegeben werden – eine Garantie, die Finalize nicht gibt. Andererseits kann die durch den Zugriffsmodifizierer Protected geschützte Finalize-Methode auch nicht von einem Client aufgerufen werden, um die Ausführung zu erzwingen, denn Protected ist für den Aufrufer gleichbedeutend mit Private.

Um diesem Problem zu begegnen, können Sie eine öffentliche Methode implementieren, die ein Client aufrufen kann. Diese Methode heißt Dispose. Damit aber nicht genug. Wir müssen im objektorientierten Sinne noch einen Riesenschritt nach vorne machen und unsere Klasse um die Schnittstelle IDisposable erweitern. Eine Schnittstelle ist einer Klasse sehr ähnlich, jedoch sind andere Richtlinien damit verbunden, die sowohl die Implementierung als auch den Nutzen einer Schnittstelle beschreiben. Wir werden uns diesen in Kapitel 6 zuwenden, auf das Verständnis der Wirkungsweise der Dispose-Methode haben sie keinen Einfluss.

Schauen wir uns zunächst den strukturellen Rahmen der Dispose-Methode an. Er lautet:


Public Class ClassA
Implements IDisposable
Public Sub Dispose() Implements IDisposable.Dispose
'Anweisungen
End Sub
End Class

In der Definition der Klasse ClassA muss die Veröffentlichung der Schnittstelle IDisposable mit dem Schlüsselwort Implements bekannt gegeben werden. Jede Methode, die von einer Schnittstelle veröffentlicht wird, muss von der Klasse, die sich ihrerseits der Dienste der Schnittstelle bedient, implementiert werden. IDisposable enthält nur die Methode Dispose. Unsere Klasse ClassA übernimmt konventionsgemäß die Methode Dispose, indem hinter der Parameterliste noch einmal angegeben wird, aus welcher Schnittstelle die Methode stammt.

Die Dispose-Methode soll dem Client die Sicherheit geben, nicht auf den GC und damit auf die Ausführung der Finalize-Methode warten zu müssen. Also muss der Code, der die beanspruchten Eigen- oder Fremdressourcen freigibt, in der Methode Dispose implementiert werden.

Zwischen den beiden Methoden besteht ein gravierender Unterschied, der die weitere Vorgehensweise bei der Programmierung nachhaltig beeinflusst: Während Finalize automatisch aufgerufen wird, setzt die Ausführung von Dispose den expliziten Aufruf durch den Benutzer voraus:


Dim obj as New ClassA
...
obj.Dispose()

Die Garantie, dass der Benutzer den Aufruf startet, kann aber niemand geben. Daran muss bei der Entwicklung einer Klasse gedacht werden, deren Objekte bei der Zerstörung fremde Ressourcen in Anspruch nehmen. Es gibt nur eine logische Schlussfolgerung, um diesem Umstand zu begegnen: Der Freigabecode muss sowohl in Dispose als auch in Finalize implementiert werden.

Es bietet sich dazu an, aus der Dispose-Methode heraus die Finalize-Methode aufzurufen, die den Freigabecode enthält. Seien Sie sich jedoch darüber bewusst: Der explizite Aufruf von Finalize führt nicht dazu, dass der vom Objekt reservierte Speicherbereich aufgegeben wird!


Public Sub Dispose() Implements IDisposable.Dispose
Finalize()
End Sub
Protected Overrides Sub Finalize()
' Anweisungen, um die beanspruchten Ressourcen freizugeben
MyBase.Finalize()
End Sub

Ein Problem dieses Codefragments ist, dass nicht nur im Falle des Aufrufs von Dispose die Methode Finalize ausgeführt wird, sondern auch dann, wenn der Garbage Collector zu einem späteren Zeitpunkt seine Arbeit verrichtet. Werden die Ressourcen aber zweimal freigegeben, führt das zu einem undefinierten Programmzustand. Um dem zu begegnen, muss die Methode SuppressFinalize der Klasse GC aufgerufen werden. SuppressFinalize stellt unter Übergabe einer Objektreferenz – in unserem Fall der Me-Referenz – sicher, dass der GC Finalize kein zweites Mal aufruft.


Public Sub Dispose() Implements IDisposable.Dispose
Finalize()
GC.SuppressFinalize(Me)
End Sub
Protected Overrides Sub Finalize()
'Anweisungen, um die beanspruchten Ressourcen freizugeben
MyBase.Finalize()
End Sub

Zum Abschluss unserer Betrachtungen müssen noch zwei Situationen berücksichtigt werden, die im Zusammenhang mit der Implementierung von Dispose während der Laufzeit auftreten können und entsprechend behandelt werden müssen:

1. Dispose könnte vom Benutzer wiederholt aufgerufen werden. Das führt wiederum zu mehreren Finalize-Aufrufen mit den vorher angedeuteten Auswirkungen eines undefinierten Programmzustands.
       
2. Nach der Ausführung von Dispose könnte eine andere Methode des Objekts aufgerufen werden, die ihrerseits versucht, auf die inzwischen freigegebene Ressource zuzugreifen.
       

Im folgenden Codefragment wird gezeigt, wie Sie diesen Problemen begegnen können. Dazu wird eine fiktive Klasse Connection instanziiert, von der wir annehmen, dass sie eine Ressource auf einem entfernten Rechner reserviert.


Public Class ClassA
Implements IDisposable
Private bolDisposed As Boolean
Private myRes As New Connection()
Public Sub Dispose() Implements IDisposable.Dispose
If Not bolDisposed Then
Finalize()
System.GC.SuppressFinalize(Me)
End If
End Sub
Protected Overrides Sub Finalize()
myRes.Dispose()
myRes = Nothing
bolDisposed = True
MyBase.Finalize()
End Sub
Public Sub DoSomething()
If Not bolDisposed Then
'Methoden des Objekts myRes aufrufen
Else
Throw New UserDefinedException()
' ...
End If
End Sub
End Class

In Finalize wird die Referenz des Objekts vom Typ Connection auf Nothing gesetzt. Weil die Aufräumarbeiten auf verschiedene Weisen angestoßen werden können, muss ein Element definiert werden, um den aktuellen Stand nachzuvollziehen. Hierzu dient die boolesche Variable bolDisposed. Ihr Zustand True kennzeichnet die bereits freigegebene Ressource.

Betrachten wir nun den Ablauf zur Laufzeit und da zunächst den Fall, dass der Benutzer die Methode Dispose eines ClassA-Objekts zum ersten Mal aufruft. Zunächst wird der Inhalt des Flags bolDisposed geprüft. Ist er False, kommt es zur Ausführung von Finalize, was die Freigabe der Ressource anstößt und das Flag True setzt. Nachdem auch die Finalisierer der Basisklassen durchlaufen sind, wird der Programmablauf mit dem Methodenaufruf SuppressFinalize beendet.

Das ist der normale Ablauf. Nun könnte der Benutzer noch ein weiteres Mal auf die Idee kommen, Dispose auszuführen. Dabei gehen wir davon aus, dass der GC zwischenzeitlich das Objekt noch nicht der endgültigen Zerstörung zugeführt hat. Die Prüfung des Flags bolDisposed, dessen Inhalt nun True ist, wird durch die bedingte Anweisung zu einer Abweisung führen.

Betrachten wir nun noch den dritten Fall. Die im obigen Codefragment der Klasse implementierte Methode DoSomething symbolisiert eine Funktionalität, welche die Fremdressource in Anspruch nimmt. Wird DoSomething aufgerufen, nachdem es keine gültige Referenz auf das Objekt myRes mehr gibt, ist die Folge ein Laufzeitfehler, der zu einer Beendigung der laufenden Anwendung führt. Um dies zu vermeiden, muss in der Methode eine Ausnahmebehandlung vorgesehen werden, die ein weiteres Arbeiten mit der Anwendung gestattet. Mit der Implementierung der Ausnahmebehandlung werden wir uns jedoch erst in Kapitel 9 eingehend beschäftigen.

Automatischer Aufruf der Methode »Dispose« durch »Using«

Neu in Visual Basic 2005 ist, dass der Aufruf der Methode Dispose auch automatisch erfolgen kann. Dazu wird ein mit dem neuen Schlüsselwort Using definierter Anweisungsblock ins Leben gerufen. Dem Schlüsselwort Using folgt die Instanziierung einer Klasse, welche die Schnittstelle IDisposable implementiert und damit auch zwangsläufig Dispose bereitstellt. Mit dem Verlassen des Anweisungsblocks wird letztgenannte Methode implizit aufgerufen.


Using obj As New ClassA
' weitere Anweisungen
End Using


Galileo Computing

4.6.3 Zusammenfassung  toptop

gp  Objekte werden freigegeben, wenn sie ihren Gültigkeitsbereich verlassen oder die Referenz explizit auf Nothing gesetzt wird. Solchermaßen freigegebene Objekte werden noch nicht sofort zerstört.
gp  Bei der Zerstörung eines Objekts durch den Garbage Collector wird der Speicherplatz, den das Objekt für sich beansprucht, automatisch freigegeben.
gp  Wann der Garbage Collector in Aktion tritt, ist unbestimmt. Als Thread niedriger Priorität wird er nur dann aktiv, wenn die Anwendung beschäftigungslos ist oder die Speicherressourcen knapp werden.
gp  Wird er ausgeführt, sucht der Garbage Collector alle unreferenzierten Objekte der aktuellen Anwendung. Danach erfolgt die Überprüfung, ob die Klassendefinitionen dieser Objekte eine Finalize-Methode implementieren, die dann gegebenenfalls vor der endgültigen Speicherplatzfreigabe ausgeführt wird.
gp  Finalize dient dazu, die von einem Objekt beanspruchten Fremdressourcen freizugeben. Da Finalize vom Garbage Collector automatisch und zu einem nicht vorhersehbaren Zeitpunkt aufgerufen wird, kann in einer Klasse eine Methode implementiert werden, über welche die Ressourcenfreigabe gesteuert wird. Dazu veröffentlicht die Klasse die Schnittstelle IDisposable und übernimmt deren Methode Dispose.
gp  Die Klasse GC stellt Methoden zur Verfügung, um den Speicherbereinigungsmechanismus zu steuern. Mit der Methode Collect wird die Speicherbereinigung angestoßen, mit der Methode SuppressFinalize ein Aufrufen des Finalisierers unterbunden.
 <<   zurück
  
  Zum Katalog
Zum Katalog: Visual Basic 2005
Visual Basic 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2005






 Visual C# 2005


Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Das Programmierhandbuch SQL Server 2005






 Das Programmier-
 handbuch
 SQL Server 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de